class Card:
    # 静态属性：花色的映射
    SUIT_MAPPING = {
        1: "♦️",
        2: "♣️",
        3: "♥️",
        4: "♠️"
    }
    # 用于将用户输入的花色字符串转换为整数
    SUIT_MAPPING_INPUT = {
        "♦️": 1,
        "♣️": 2,
        "♥️": 3,
        "♠️": 4
    }

    # 静态属性：点数的映射（展示用）
    RANK_MAPPING_DISPLAY = {
        1: "A",
        11: "J",
        12: "Q",
        13: "K"
    }
    # 用于将用户输入的点数字符串转换为整数
    RANK_MAPPING_INPUT = {
        "A": 1,
        "J": 11,
        "Q": 12,
        "K": 13
    }

    def __init__(self, card_id, name, suit, rank, category):
        """
        初始化卡牌对象
        :param card_id: 卡牌ID
        :param name: 牌名 (如 "杀", "闪", "顺手牵羊")
        :param suit: 花色，使用整数表示（建议：1=♦️, 2=♣️, 3=♥️, 4=♠️）
        :param rank: 点数，整数 1～13（1 表示 A，11=J, 12=Q, 13=K）
        :param category: 类别 (如 "基本牌", "锦囊牌", "装备牌")
        """
        self.card_id = card_id
        self.name = name
        self.suit = suit    # 内部使用整数表示花色
        self.rank = rank    # 内部使用整数表示点数
        self.category = category

    def __repr__(self):
        # 内部存储为数字，但展示时转换为符号
        return (f"Card({self.card_id}, {self.name}, "
                f"{self.get_suit_display()}, {self.get_rank_display()}, {self.category})")

    def to_tuple(self):
        """
        返回卡牌信息的元组，全部为基本数据类型：
        (card_id: int, name: str, suit: int, rank: int, category: str)
        """
        return (self.card_id, self.name, self.suit, self.rank, self.category)

    def get_suit_display(self):
        """返回花色的展示字符串"""
        return Card.SUIT_MAPPING.get(self.suit, str(self.suit))

    def get_rank_display(self):
        """返回点数的展示字符串"""
        return Card.RANK_MAPPING_DISPLAY.get(self.rank, str(self.rank))

    # 装备类型接口：装备可细化为四类：武器、 防具、 进攻马、 防御马
    def is_weapon(self):
        """返回该卡牌是否为武器牌（card_id 在 136 至 147）"""
        return 136 <= self.card_id <= 147

    def is_armor(self):
        """返回该卡牌是否为防具牌（card_id 在 148 至 153）"""
        return 148 <= self.card_id <= 153

    def is_offensive_horse(self):
        """返回该卡牌是否为进攻马（card_id 在 154 至 156）"""
        return 154 <= self.card_id <= 156

    def is_defensive_horse(self):
        """返回该卡牌是否为防御马（card_id 在 155 至 160）"""
        return 155 <= self.card_id <= 160

    @classmethod
    def create_card_from_input(cls, card_id, name, suit, rank, category):
        """
        用户友好的构造方法：
         - suit: 用户可以传入花色符号（如 "♦️"）或者整数（1~4）
         - rank: 用户可以传入点数字符串（如 "A", "J", "Q", "K" 或 "10"）或者整数（1~13）
         - 其他字段直接传入
        内部统一转换为基本数据类型，然后调用标准构造函数。
        """
        # 使用类静态属性进行花色转换
        if isinstance(suit, str):
            suit = Card.SUIT_MAPPING_INPUT.get(suit, None)
            if suit is None:
                raise ValueError(f"Invalid suit input: {suit}")
        
        # 使用类静态属性进行点数转换
        if isinstance(rank, str):
            # 如果输入的字符串在映射中，则转换，否则尝试转换为整数
            rank = Card.RANK_MAPPING_INPUT.get(rank, None) or int(rank)
        
        return cls(card_id, name, suit, rank, category)
    @classmethod
    def create_virtual_card(cls, name, suit, rank):
        """
        构造一个用于查询或虚拟牌的 Card 对象。
        用户只需提供牌名、花色和点数，其它字段设为默认值，
        方便后续查询或在玩法中打出虚拟牌使用。

        输入:
        - name: 卡牌名称（如 "杀"）
        - suit: 花色，可以是符号（如 "♦️"）或整数（1~4）
        - rank: 点数，可以是字符串（如 "A", "K", "10"）或整数（1~13）

        输出:
        - 返回一个 Card 对象，card_id 设为0，category 为空字符串
        """
        card_id = 0   # id 是不存在的 0， 表示这是虚拟牌
        category = ""
        return cls.create_card_from_input(card_id, name, suit, rank, category)
